<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
</head>
<body>
	<canvas id="canvas" width="400" height="400"></canvas>
	
	<script type="text/javascript">
		/** 球类 **/
		class Ball{
			constructor(radius=40, color='#ff0000'){
				this.x = 0;
				this.y = 0;
				this.radius = radius;
				this.rotation = 0;
				this.scaleX = 1;
				this.scaleY = 1;
				this.color = color;
				this.lineWidth = 1;
			}
			draw(context){
				context.save();
				context.translate(this.x, this.y); //重新映射画布上的 (0,0) 位置
				context.rotate(this.rotation); //旋转当前绘图
				context.scale(this.scaleX, this.scaleY);
				context.lineWidth = this.lineWidth;
				context.strokeStyle = this.color;
				context.fillStyle = this.color;
				context.beginPath();
				//x, y, radius, start_angle, end_angle, anti-clockwise
				context.arc(0, 0, this.radius, 0, (Math.PI * 2), true);
				context.closePath();
				context.fill();
				if (this.lineWidth > 0) {
					context.stroke();
				}
				context.restore();
			}
		}
		
		/** 箭头类 **/
		class Arrow{
			constructor(){
				this.x = 0;
				this.y = 0;
				this.color = '#ffff00';
				this.rotation = 0;
			}
			draw(context){
				context.save();
				context.translate(this.x, this.y); //重新映射画布上的 (0,0) 位置
				context.rotate(this.rotation); //旋转当前绘图
				context.lineWidth = 2;
				context.fillStyle = this.color;
				context.beginPath();
				context.moveTo(-50, -25);
				context.lineTo(0, -25);
				context.lineTo(0, -50);
				context.lineTo(50, 0);
				context.lineTo(0, 50);
				context.lineTo(0, 25);
				context.lineTo(-50, 25);
				context.lineTo(-50, -25);
				context.closePath();
				context.fill();
				context.stroke(); //绘制已定义的路径
				context.restore(); //返回之前保存过的路径状态和属性
			}
		}
		
		/** 飞船类 **/
		class Ship{
			constructor(){
				this.x = 0;
				this.y = 0;
				this.width = 25;
				this.height = 20;
				this.rotation = 0;
				this.showFlame = false;
			}
			draw(context){
				context.save();
				context.translate(this.x, this.y);
				context.rotate(this.rotation);
				context.lineWidth = 1;
				context.strokeStyle = "#000";
				context.beginPath();
				context.moveTo(10, 0);
				context.lineTo(-10, 10);
				context.lineTo(-5, 0);
				context.lineTo(-10, -10);
				context.lineTo(10, 0);
				context.stroke();
				if (this.showFlame) {
					context.beginPath();
					context.moveTo(-7.5, -5);
					context.lineTo(-15, 0);
					context.lineTo(-7.5, 5);
					context.stroke();
				}
				context.restore();
			}
		}
		
		/** 方形 **/
		class Box{
			constructor(width=50, height=50, color='#ff0000') {
			  this.x = 0;
				this.x = 0;
				this.y = 0;
				this.width = width;
				this.height = height;
				this.vx = 0;
				this.vy = 0;
				this.rotation = 0;
				this.scaleX = 1;
				this.scaleY = 1;
				this.color = color;
				this.lineWidth = 1;
			}
			draw(context){
				context.save();
				context.translate(this.x, this.y);
				context.rotate(this.rotation);
				context.scale(this.scaleX, this.scaleY);
				context.lineWidth = this.lineWidth;
				context.fillStyle = this.color;
				context.strokeStyle = this.color;
				context.beginPath();
				context.rect(0, 0, this.width, this.height);
				context.closePath();
				context.fill();
				if (this.lineWidth > 0) {
					context.stroke();
				}
				context.restore();
			}
		}
		
		/** 线 **/
		class Line{
			constructor(x1, y1, x2, y2) {
			  this.x = 0;
				this.y = 0;
				this.x1 = (x1 === undefined) ? 0 : x1;
				this.y1 = (y1 === undefined) ? 0 : y1;
				this.x2 = (x2 === undefined) ? 0 : x2;
				this.y2 = (y2 === undefined) ? 0 : y2;
				this.rotation = 0;
				this.scaleX = 1;
				this.scaleY = 1;
				this.lineWidth = 1;
			}
			draw(context){
				context.save();
				context.translate(this.x, this.y);
				context.rotate(this.rotation);
				context.scale(this.scaleX, this.scaleY);
				context.lineWidth = this.lineWidth;
				context.beginPath();
				context.moveTo(this.x1, this.y1);
				context.lineTo(this.x2, this.y2);
				context.closePath();
				context.stroke();
				context.restore();
			}
			getBounds(){
				if (this.rotation === 0) {
					var minX = Math.min(this.x1, this.x2),
							minY = Math.min(this.y1, this.y2),
							maxX = Math.max(this.x1, this.x2),
							maxY = Math.max(this.y1, this.y2);
					return {
						x: this.x + minX,
						y: this.y + minY,
						width: maxX - minX,
						height: maxY - minY
					}
				} else {
					var sin = Math.sin(this.rotation),
							cos = Math.cos(this.rotation),
							x1r = cos * this.x1 + sin * this.y1,
							x2r = cos * this.x2 + sin * this.y2,
							y1r = cos * this.y1 + sin * this.x1,
							y2r = cos * this.y2 + sin * this.x2;
					return {
						x: this.x + Math.min(x1r, x2r),
						y: this.y + Math.min(y1r, y2r),
						width: Math.max(x1r, x2r) - Math.min(x1r, x2r),
						height: Math.max(y1r, y2r) - Math.min(y1r, y2r)
					};
				}
			}
		}
		
		/** 球3D **/
		class Ball3d{
			constructor(radius=40, color='#ff0000') {
			  this.x = 0;
				this.y = 0;
				this.xpos = 0;
				this.ypos = 0;
				this.zpos = 0;
				this.radius = radius;
				this.vx = 0;
				this.vy = 0;
				this.vz = 0;
				this.mass = 1;
				this.rotation = 0;
				this.scaleX = 1;
				this.scaleY = 1;
				this.color = color;
				this.lineWidth = 1;
				this.visible = true;
			}
			draw(context){
				context.save();
				context.translate(this.x, this.y);
				context.rotate(this.rotation);
				context.scale(this.scaleX, this.scaleY);
				context.lineWidth = this.lineWidth;
				context.fillStyle = this.color;
				context.strokeStyle = this.color;
				context.beginPath();
				//x, y, radius, start_angle, end_angle, anti-clockwise
				context.arc(0, 0, this.radius, 0, (Math.PI * 2), true);
				context.closePath();
				context.fill();
				if (this.lineWidth > 0) {
					context.stroke();
				}
				context.restore();
			}
		}
		
		
		var canvas = document.getElementById('canvas'),
				context = canvas.getContext('2d'),
				ball = new Ball();
				ball.draw(context);
				
				arrow = new Arrow();
				arrow.draw(context);
				
				ship = new Ship();
				ship.draw(context);
				
				box = new Box();
				box.draw(context);
				
				line = new Line(0, 0, 300, 0);
				line.draw(context);
				
				ball3d = new Ball3d();
				ball3d.draw(context);
	</script>
</body>
</html>